package label.propagation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import graphic.Graph;

/**
 * @author ZhangyiA
 * @describe: 抽样，h% ，得到 sizeOne 集合
 * @date 2021/07/21
 */

public class CGSamp {

    private Propagation lpaPropagation;
    private static final double SAMPLE_RATE = 0.6;  // 采样率 后期是变动的 0.1 - 1
    private Graph graph;
    private ArrayList<Integer> sizeOne;

    public CGSamp(Propagation lpaPropagation , Graph graph){
        this.lpaPropagation = lpaPropagation;
        this.graph = graph;
        this.sizeOne = new ArrayList<>();
    }

    // 抽样获得 子图大小为 1 的子图
    public void getSize1FrequentSet(){
        Map<Integer , ArrayList<Integer>> com = lpaPropagation.getLPACommunityPartitionResult();
        for(Map.Entry<Integer , ArrayList<Integer>> entry : com.entrySet()){
//            sampleWithLabel1(entry.getValue()); // 从每个社区中再按照标签聚类进行抽样(适合小图)
            sampleWithLabel(entry.getValue()); // 从每个社区中再按照标签聚类进行抽样
        }
        System.out.println("class CGSamp --> step3: get " + SAMPLE_RATE * 100  + "% sizeOne result : " + sizeOne.size());
    }

    public void sampleWithLabel(ArrayList<Integer> com){
        int size = com.size();
        int count = (int) (size * SAMPLE_RATE);
        Set<Integer> set = new HashSet<>();
        for(int i = 0 ; i < count ; i ++){
            int index = (int) (Math.random() * size); // 随机抽取第 index 个顶点
            while(set.contains(index)){ // 避免重复抽取
                index = (int)(Math.random() * size);
            }
            set.add(index);
            int nodeVal = com.get(index);
            if(graph.head[nodeVal] != -1) // 说明该顶点没有后续顶点
                sizeOne.add(nodeVal);
        }
    }

    public void sampleWithLabel1(ArrayList<Integer> com){
        Map<Integer , ArrayList<Integer>> label_nodeArray = new HashMap<>();
        for(Integer nodeVal : com){
            int vertex_label = graph.vertices[nodeVal].getLabel();
            ArrayList<Integer> temp = label_nodeArray.containsKey(vertex_label) ? label_nodeArray.get(vertex_label) : new ArrayList<>();
            temp.add(nodeVal);
            label_nodeArray.put(vertex_label , temp);
        }
        for(Map.Entry<Integer , ArrayList<Integer>> entry : label_nodeArray.entrySet()){
            int size = entry.getValue().size();
            int count = (int) Math.ceil(size * SAMPLE_RATE); // 从改标签中抽取 count 个顶点
//            System.out.println( "count = " + size + " * " + SAMPLE_RATE + " = " + (int) Math.ceil(size * SAMPLE_RATE));
            Set<Integer> set = new HashSet<>();
            for(int i = 0 ; i < count ; i ++){
                int index = (int) (Math.random() * size); // 随机抽取第 index 个顶点
                while(set.contains(index)){ // 避免重复抽取
                    index = (int)(Math.random() * size);
                }
                set.add(index);
                int nodeVal = entry.getValue().get(index);
                if(graph.head[nodeVal] != -1) // 说明该顶点没有后续顶点
                    sizeOne.add(nodeVal);
            }
        }
    }


    public ArrayList<Integer> getSizeOne() {
        return sizeOne;
    }
}
